/*******************************************************************************
 * This file is part of the EEG-database project
 * 
 *   ==========================================
 *  
 *   Copyright (C) 2013 by University of West Bohemia (http://www.zcu.cz/en/)
 *  
 *  ***********************************************************************************************************************
 *  
 *   Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 *   the License. You may obtain a copy of the License at
 *  
 *       http://www.apache.org/licenses/LICENSE-2.0
 *  
 *   Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 *   an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 *   specific language governing permissions and limitations under the License.
 *  
 *  ***********************************************************************************************************************
 *  
 *   GroupMultiController.java, 2013/10/02 00:01 Jakub Rinkes
 ******************************************************************************/
package cz.zcu.kiv.eegdatabase.logic.controller.group;

import cz.zcu.kiv.eegdatabase.data.dao.AuthorizationManager;
import cz.zcu.kiv.eegdatabase.data.dao.GenericDao;
import cz.zcu.kiv.eegdatabase.data.dao.PersonDao;
import cz.zcu.kiv.eegdatabase.data.dao.ResearchGroupDao;
import cz.zcu.kiv.eegdatabase.data.pojo.Person;
import cz.zcu.kiv.eegdatabase.data.pojo.ResearchGroup;
import cz.zcu.kiv.eegdatabase.data.pojo.ResearchGroupMembership;
import cz.zcu.kiv.eegdatabase.data.pojo.ResearchGroupMembershipId;
import cz.zcu.kiv.eegdatabase.logic.Util;
import cz.zcu.kiv.eegdatabase.logic.util.Paginator;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * Delegate class for multicontroller which processes groups section.
 *
 * @author Jindrich Pergler
 */
public class GroupMultiController extends MultiActionController {

    private AuthorizationManager auth;
    private ResearchGroupDao researchGroupDao;
    private PersonDao personDao;
    private GenericDao<ResearchGroupMembership, ResearchGroupMembershipId> membershipDao;
    private static final int ITEMS_PER_PAGE = 20;

    public ModelAndView editGroupRole(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView mav = new ModelAndView("groups/editGroupRole");
        setPermissionToRequestGroupRole(mav, personDao.getLoggedPerson());
        return mav;
    }

    public ModelAndView list(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView mav = new ModelAndView("groups/list");
        setPermissionToRequestGroupRole(mav, personDao.getLoggedPerson());

        Paginator paginator = new Paginator(researchGroupDao.getCountForList(), ITEMS_PER_PAGE);
        int page = 1;
        try {
            page = Integer.parseInt(request.getParameter("page"));
        } catch (Exception e) {
        }
        paginator.setActualPage(page);

        List<ResearchGroup> list = researchGroupDao.getGroupsForList(paginator.getFirstItemIndex(), ITEMS_PER_PAGE);
        mav.addObject("groupList", list);
        mav.addObject("paginator", paginator.getLinks());
        return mav;
    }

    public ModelAndView myGroups(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView mav = new ModelAndView("groups/myGroupsList");
        setPermissionToRequestGroupRole(mav, personDao.getLoggedPerson());
        List<ResearchGroup> ownedList = researchGroupDao.getResearchGroupsWhereOwner(personDao.getLoggedPerson());
        mav.addObject("ownedList", ownedList);
        List<ResearchGroup> memberList = researchGroupDao.getResearchGroupsWhereMember(personDao.getLoggedPerson());
        mav.addObject("memberList", memberList);
        return mav;
    }

    public ModelAndView detail(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView mav = new ModelAndView("groups/detail");
        setPermissionToRequestGroupRole(mav, personDao.getLoggedPerson());
        int id = Integer.parseInt(request.getParameter("groupId"));

        mav.addObject("userIsMemberInGroup", auth.userIsMemberInGroup(id));
        mav.addObject("userIsExperimenterInGroup", auth.userIsExperimenterInGroup(id));
        mav.addObject("userIsAdminInGroup", auth.userIsAdminInGroup(id));

        ResearchGroup group = researchGroupDao.read(id);
        mav.addObject("researchGroup", group);
        return mav;
    }

    public ModelAndView listOfMembers(HttpServletRequest request, HttpServletResponse response) {
        ModelAndView mav = new ModelAndView("groups/listOfMembers");
        setPermissionToRequestGroupRole(mav, personDao.getLoggedPerson());

        int groupId = 0;
        try {
            groupId = Integer.parseInt(request.getParameter("groupId"));
        } catch (NumberFormatException e) {
        }

        if (!auth.userIsExperimenterInGroup(groupId)) {
            mav.setViewName("redirect:/groups/detail.html?groupId=" + groupId);
            return mav;
        }
//
        mav.addObject("userIsAdminInGroup", auth.userIsAdminInGroup(groupId));
        mav.addObject("memberList", researchGroupDao.getListOfGroupMembers(groupId));
        mav.addObject("groupId", groupId);
        mav.addObject("groupTitle", researchGroupDao.read(groupId).getTitle());
        return mav;
    }

    public ModelAndView changeRole(HttpServletRequest request, HttpServletResponse response) {
        // If we don't get the group id, redirect to list of groups
        ModelAndView mav = new ModelAndView("redirect:/groups/list.html");
        setPermissionToRequestGroupRole(mav, personDao.getLoggedPerson());

        int groupId = 0;
        int personId = 0;
        String role = "";
        try {
            groupId = Integer.parseInt(request.getParameter("groupId"));
            // Now we know the group id, so we change the redirect to the list of members
            mav.setViewName("redirect:/groups/list-of-members.html?groupId=" + groupId);
            personId = Integer.parseInt(request.getParameter("personId"));
            role = request.getParameter("role");
        } catch (NumberFormatException e) {
            return mav;
        }

        if (!auth.userIsAdminInGroup(groupId)) {
            // If user has no permission for changing role, we will return back to the list of members
            return mav;
        }

        if ((!role.equals(Util.GROUP_ADMIN))
                && (!role.equals(Util.GROUP_EXPERIMENTER))
                && (!role.equals(Util.GROUP_READER))
                && (!role.equals("REMOVE"))) {
            // If specified role is not correct, return MAV so we return back with no changes
            return mav;
        }

        // Now we can make changes
        ResearchGroupMembership membership = membershipDao.read(new ResearchGroupMembershipId(personId, groupId));
        if (role.equals("REMOVE")) {
            membershipDao.delete(membership);
        } else {
            membership.setAuthority(role);
        }

        return mav;
    }

    /**
     * @return true if user has ROLE_ADMIN, ROLE_USER, or is part of at least 1 group
     */
    private static boolean isAuthorizedToRequestGroupRole(Person loggedUser) {
        return (loggedUser.getAuthority().equals(Util.ROLE_ADMIN)
                || loggedUser.getAuthority().equals(Util.ROLE_USER)
                || !loggedUser.getResearchGroupMemberships().isEmpty());
    }

    public static void setPermissionToRequestGroupRole(Map modelMap, Person loggedUser) {
        if (isAuthorizedToRequestGroupRole(loggedUser)) {
            modelMap.put("userCanRequestGroupRole", true);
        }
    }

    public static void setPermissionToRequestGroupRole(ModelAndView mav, Person loggedUser) {
        if (isAuthorizedToRequestGroupRole(loggedUser)) {
            mav.addObject("userCanRequestGroupRole", true);
        }
    }

    public ResearchGroupDao getResearchGroupDao() {
        return researchGroupDao;
    }

    public void setResearchGroupDao(ResearchGroupDao researchGroupDao) {
        this.researchGroupDao = researchGroupDao;
    }

    public PersonDao getPersonDao() {
        return personDao;
    }

    public void setPersonDao(PersonDao personDao) {
        this.personDao = personDao;
    }

    public AuthorizationManager getAuth() {
        return auth;
    }

    public void setAuth(AuthorizationManager auth) {
        this.auth = auth;
    }

    public GenericDao<ResearchGroupMembership, ResearchGroupMembershipId> getMembershipDao() {
        return membershipDao;
    }

    public void setMembershipDao(GenericDao<ResearchGroupMembership, ResearchGroupMembershipId> membershipDao) {
        this.membershipDao = membershipDao;
    }
}
